home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 112 (1989-11-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 112 (1989-11-15)(Ossowski, Stefan)(DE)(PD).adf / VirusX_V3.20 / virusx.c < prev    next >
Text File  |  1989-07-02  |  68KB  |  1,985 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /*                                                                      */
  4. /*                                VirusX                                */
  5. /*                                                                      */
  6. /*                           by Steve Tibbett                           */
  7. /*                                                                      */
  8. /*                                                                      */
  9. /*              Please - if you find a new virus, Send me a copy!       */
  10. /*              (And warn me it's on the disk!).  I want to keep        */
  11. /*              this program current.  (Feel free to put something      */
  12. /*              neat on the disk also!)                                 */
  13. /*                                                                      */
  14. /*  This version of VirusX is done with the Lattice 5.0                 */
  15. /*  compiler.  The Lattice compiler, with the help of John Toebes,      */
  16. /*  gave me an executable almost 4K smaller than the best I could       */
  17. /*  get out of Manx.  Reason enough for me to switch!                   */
  18. /*                                                                      */
  19. /*  The Makefile included in the "source.zoo" file you should have      */
  20. /*  gotten in the VirusX.Zoo file this came from, is set up for the     */
  21. /*  MANX Make Utility.  Switching to Lattice's LMK should be easy,      */
  22. /*  but I've had no reason to.  The important thing is the command      */
  23. /*  line switches and the BLINK command line.                           */
  24. /*                                                                      */
  25. /*  Thanks to John Toebes for a lot of help getting it going, and       */
  26. /*  thanks to Dan James for providing the routine down at the bottom    */
  27. /*  that actually takes the IRQ Virus out of executable files.          */
  28. /*                                                                      */
  29. /************************************************************************/
  30. /*                                                                      */
  31. /*  History:                                                            */
  32. /*  --------                                                            */
  33. /*      April '88 or so:  V1.0 written and released.                    */
  34. /*     A few days later:  V1.01 released.  V1.0 wrote garbage to the    */
  35. /*                        disk if it was write protected then fixed.    */
  36. /*          27-March-88:  V1.2 released.  V1.2's purpose in life was    */
  37. /*                        to deal with the Byte Bandit virus.           */
  38. /*                        (Actually, it's well after midnight - make    */
  39. /*                        that March 28th. :)                           */
  40. /*          28-March-88:  Oops, V1.2 was 3K or so bigger than it needed */
  41. /*                        to be.  Fix it, release v1.21.                */
  42. /*           15-June-88:  V1.3, V1.2 cleaned up and made smaller.       */
  43. /*            8-July-88:  V1.4.  Revenge virus checking, Viewbooting,   */
  44. /*                        check for SCA in RAM, more cleaning up.       */
  45. /*           24-July-88:  V1.5, only change was the addition of the     */
  46. /*                        Byte Warrior virus.                           */
  47. /*             1-Aug-88:  V1.6 (busy week), Dan Mosedale sent me the    */
  48. /*                        Northstar Virus.  Nuked it.                   */
  49. /*            18-Aug-88:  V1.7 - after 2 weeks off, got the Obelisk     */
  50. /*                        Softworks crew virus.                         */
  51. /*     a few days later:  V1.71, can't remember why.                    */
  52. /*   September Sometime:  Biggest mistake of my life, released V2.0.    */
  53. /*         3 days later:  Bigger mistake:  Released V2.01 - which was   */
  54. /*                        2.0 with another bug added.  Argh.            */
  55. /*             6-Nov-88:  Finally got some time to clean things up,     */
  56. /*                        check out the startup code bugs, clean up the */
  57. /*                        docs and source, and release V2.1.  There     */
  58. /*                        haven't been any new viruses in about a month */
  59. /*                        now, but I hear one or two are on the way.    */
  60. /*            31-Dec-88:  Got the IRQ virus yesterday.  Neat one!       */
  61. /*                        Releasing V3.0 tonite or tomorrow to handle   */
  62. /*                        it.  See description below.                   */
  63. /*            04-Jan-89:  Got 2 new viruses, released 3.1.              */
  64. /*            18-Feb-89:  And boy, am I tired.  8 (count 'em) 8 new     */
  65. /*                        viruses in this version.  Ack!  DOUBLE        */
  66. /*                        the last version.  New option: CHECK, good    */
  67. /*                        for including VirusX with a commercial        */
  68. /*                        program.  V3.20                               */
  69. /*                                                                      */
  70. /************************************************************************/
  71. /*                                                                      */
  72. /*  Viruses Dealt With:                                                 */
  73. /*  -------------------                                                 */
  74. /*                                                                      */
  75. /*      SCA             - The SCA is the simplest virus to deal with,   */
  76. /*                        as it's not actually DOING anything except    */
  77. /*                        hiding in memory, until you reboot.           */
  78. /*                        We just look at CoolCapture and fix it to get */
  79. /*                        it out of RAM.                                */
  80. /*                                                                      */
  81. /*      Byte Bandit     - The Byte Bandit virus takes the DoIO() vector */
  82. /*                        and redirects it through itself.  Thus, any   */
  83. /*                        attempt to read or write the boot block (ie,  */
  84. /*                        AmigaDOS trying to figure out what kind of    */
  85. /*                        disk it is) results in the BB writing itself  */
  86. /*                        onto that disk.  VirusX couldn't just rewrite */
  87. /*                        the boot block, we have to get him out of RAM */
  88. /*                        first.  This virus also has an interrupt that */
  89. /*                        crashes the machine every 5 minutes or so     */
  90. /*                        after it's infected a few of your disks.  Ow. */
  91. /*                        It stays in memory not via the Capture        */
  92. /*                        vectors, but by a Resident module.            */
  93. /*                                                                      */
  94. /*      Revenge         - Basically, a Byte Bandit clone except it will */
  95. /*                        bring up an obscene pointer a few minutes     */
  96. /*                        after you reboot.  We treat it much like the  */
  97. /*                        byte bandit.                                  */
  98. /*                                                                      */
  99. /*      Byte Warrior    - Jumps right into 1.2 Kickstart.  Won't work   */
  100. /*                        under 1.3.  Hangs around via Resident struct, */
  101. /*                        doesn't do any damage.                        */
  102. /*                                                                      */
  103. /*      North Star      - Like SCA, hangs around via CoolCapture,       */
  104. /*                        killing CoolCapture kills the North Star.     */
  105. /*                                                                      */
  106. /*      Obelisk Softworks Crew                                          */
  107. /*                      - Hangs around via CoolCapture, also            */
  108. /*                        watches reads of DoIO() (but doesn't          */
  109. /*                        infect EVERY disk - onlyt ones you boot       */
  110. /*                        off of)                                       */
  111. /*                                                                      */
  112. /*       IRQ            - This is the FIRST Non-Bootblock Virus.        */
  113. /*                        It copies itself from place to place via the  */
  114. /*                        first executable program found in your        */
  115. /*                        startup-sequence.  It SetFunction's           */
  116. /*                        OldOpenLibrary(), has a KickTagPtr,           */
  117. /*                        and lives in the first hunk of an             */
  118. /*                        infected program.                             */
  119. /*                        THANKS! to Gary Duncan and Henrik Clausen for */
  120. /*                        being the first to send this one to me!       */
  121. /*                                                                      */
  122. /*  Pentagon Circle     - This one looks at the DoIO vector, and has    */
  123. /*                        a CoolCapture vector.  It will write itself   */
  124. /*                        over any virus inserted, but not onto         */
  125. /*                        anything else.  (Neat idea!).  No danger,     */
  126. /*                        easy to eliminate.  Holding left button       */
  127. /*                        while booting with this one shows different   */
  128. /*                        screen colour, but doesn't get rid of it.     */
  129. /*                        Thanks to Bill at CMI (CMI*BILL on Plink)     */
  130. /*                        for sending me this one!                      */
  131. /*                                                                      */
  132. /*  SystemZ Virus Protector                                             */
  133. /*                      - I took this one out.  It's not really a       */
  134. /*                        'Virus' in that it won't overwrite a disk     */
  135. /*                        without asking you first.  Besides, it seems  */
  136. /*                        a lot of people LIKE the SystemZ Virus        */
  137. /*                        Protector (though it isn't perfect).          */
  138. /*                                                                      */
  139. /*   Lamer Exterminator - THIS one was a bugger.  Yet another virus     */
  140. /*                        aimed at hurting people.  Y'see, a Lamer      */
  141. /*                        is apparently the worst kind of pirate -      */
  142. /*                        one who doesn't crack software, doesn't       */
  143. /*                        write software, just collects names and       */
  144. /*                        addresses and collects and spreads software.  */
  145. /*                        Lamers don't do anybody any good - and the    */
  146. /*                        guy behind this Virus took it upon himself    */
  147. /*                        to make their (and our) lives miserabler.     */
  148. /*                        Anyway, this virus loads into RAM into a      */
  149. /*                        different location every time (using a        */
  150. /*                        random location).  It is encrypted on the     */
  151. /*                        disk so you can't SEE the name of it, and     */
  152. /*                        it never actually SHOWS the name (but it's    */
  153. /*                        definately there).  It changes the            */
  154. /*                        encryption key used each time it is written   */
  155. /*                        back to disk.  It has a counter and will      */
  156. /*                        wait until the machine has been reset 2 times */
  157. /*                        OR until 3 disks have been infected, and will */
  158. /*                        then pick a DATA block (Only a DATA block -   */
  159. /*                        FFS disks are safe, I guess), randomly, and   */
  160. /*                        will write the word 'LAMER!' all through it.  */
  161. /*                        This is obviously not good, and will cause    */
  162. /*                        random disk errors.  This is the worst kind   */
  163. /*                        of havoc to wreak on the new user - and this  */
  164. /*                        virus is EVERYWHERE!  I've gotten it from 5   */
  165. /*                        people in the last week alone (all from       */
  166. /*                        different countries!  Ack!).  Anyways, credit */
  167. /*                        for being the first with this one is          */
  168. /*                        Christian Schneider.  Thanks, Christian!      */
  169. /*  Might as well break the margin convention here, eh?  Anyways,       */
  170. /*  something else I thought of about this virus:  It introduces a NEW  */
  171. /*  way for a Virus to stay in RAM.  Y'see, if ExecBase is okay at      */
  172. /*  reboot time (Exec keeps a checksum, among other things, and checks  */
  173. /*  to see if anything has been corrupted quite carefully).  Anyways,   */
  174. /*  if Exec thinks ExecBase is okay, it doesn't bother rebuilding it.   */
  175. /*  Sooo, this virus sets the SumKickData() vector to point at itself.  */
  176. /*  Then at Reboot when this vector gets called after reset, the virus  */
  177. /*  ReInstalls himself.  At least this is what I think is happening.    */
  178. /*  This virus sets up a Resident structure, but never sets the Match   */
  179. /*  Word - either this means we don't need the MatchWord or it means    */
  180. /*  his SumKickData() is doing the recovery job - either way, it's      */
  181. /*  new!  3 points for originality.                                     */
  182. /*                                                                      */
  183. /*  Graffiti - The first virus to come with rotating 3-d graphics!      */
  184. /*             It's neat - you might want to trigger it (I'm not sure   */
  185. /*             how) before nuking it.  Anyway, this one just sets       */
  186. /*             CoolCapture(), does something with DoIO() during the     */
  187. /*             reboot but sets it back to normal before anybody gets    */
  188. /*             to look at it.  Lots of code is taken by the graphics    */
  189. /*             stuff.  I just clear the CoolCapture vector.  [yawn]     */
  190. /*                                                                      */
  191. /*  Old Northstar - Poof.                        */
  192. /*                                                                      */
  193. /*  16 Bit Crew - Well, I didn't actually have to DO anything to get    */
  194. /*         VirusX to recognize it... because it seems to operate  */
  195. /*               like the Graffiti Virus.  If the 16 bit crew is in     */
  196. /*               RAM, VirusX will say it removed the Graffiti virus.    */
  197. /*               Oh well.  8-)                                          */
  198. /*                                                                      */
  199. /*  DiskDoktor - I spent more time on this one than on any other.       */
  200. /*               Y'see, this virus does lots of things.  The first one  */
  201. /*               for some reason was quite funny to me.  heh            */
  202. /*               What it would do is after you have rebooted 5 times,   */
  203. /*               each time you reboot after that, the virus would eat   */
  204. /*               10K times the total number of reboots - so after       */
  205. /*               rebooting 10 times, you would be short about 100K.     */
  206. /*               This virus also starts up another TASK.  I'm not       */
  207. /*               exactly sure when it happens, but another task named   */
  208. /*               'clipboard.device' will appear at a priority of -120,  */
  209. /*               and will continually bash the Virus' vectors into the  */
  210. /*               Coldcapture, Coolcapture, Warmcapture (which it sets   */
  211. /*               to $ff000000 just to annoy), and the DoIO() vector.    */
  212. /*               When I was working on this one, I figured I just had   */
  213. /*               to restore the old values to the DoIO() vector, but as */
  214. /*               soon as I did so, the Virus restored them - and since  */
  215. /*               I didn't disassemble the entire thing, I didn't realize*/
  216. /*               this until I wasted time looking for other faults.     */
  217. /*               This one also allocates some memory, copies some code  */
  218. /*               out of Exec into this memory, and executes it.  I      */
  219. /*               never bothered to figure out why - Once it's gone, it's*/
  220. /*               gone.                                                  */
  221. /*                                                                      */
  222. /*  Thanks also to Robb Walton for being the first to send one of the   */
  223. /*  other ones, (but I can't remember which one anymore... 8-(  )       */
  224. /************************************************************************/
  225. /*                                                                      */
  226. /*  Notes on making VirusX yourself:  The source is included mainly     */
  227. /*  for your perusal, not so that you can modify it and redistribute    */
  228. /*  it.  I've modified Manx's _main.c module to make the detach         */
  229. /*  from the initial CLI work properly.  I can't redistribute this      */
  230. /*  module since it's copyright manx, so here's VirusX without it.      */
  231. /*  It will compile and run, but if you run it from WB, it won't quit.  */
  232. /*  The version I've supplied should do everything just fine.           */
  233. /*                                                                      */
  234. /************************************************************************/
  235.  
  236.  
  237. #include <stdio.h>
  238. #include <ctype.h>
  239. #include <stdlib.h>
  240. #include <exec/types.h>
  241. #include <intuition/intuition.h>
  242. #include <devices/bootblock.h>
  243. #include <devices/trackdisk.h>        /*   /               */
  244. #include <exec/execbase.h>        /*  <-- include files  */
  245. #include <exec/memory.h>        /*   \               */
  246. #include <libraries/dos.h>        
  247. #include <libraries/dosextens.h>
  248. #include <pragmas/all.h>
  249. #include <proto/all.h>
  250. #include <String.h>
  251. #include "virusx.i" /* Virusx.i is an ANSI thing.  It's got Protoypes. */
  252.             /* (or used to anyway)                    */
  253.  
  254. /* Latticeisms */
  255.  
  256. /* What's that you say?  C is hard to read? */
  257.  
  258. void MemCleanup() {}
  259. void RawDoFmt(char *, long *, void (*)(), char*);
  260. #pragma syscall RawDoFmt 20a ba9804
  261. void __regargs prbuf(char c);
  262. int __regargs sprintf(char *buf, char *ctl, char *args) { RawDoFmt(ctl, (long *)&args, prbuf, buf); return(strlen(buf)); }
  263. void __regargs prbuf(char c) {__builtin_emit(0x16c0);}
  264.  
  265. /******************************************************************/
  266. /* In case you're interested, that little mess above is a routine */
  267. /* supplied by John Toebes which changes sprintf() from using the */
  268. /* compiler's library into something that uses the ROM code found */
  269. /* in Kickstart.  Sooo, it made VirusX about 1.2K or so smaller!! */
  270. /* Feel free to steal this and use it wherever.  However, the new */
  271. /* sprintf function can't handle a lot of things - check the Exec */
  272. /* manual (I believe) for details.  Neat formatting here, eh? 8-) */
  273. /******************************************************************/
  274.  
  275. char WhatHappened;    /* huh?? */
  276.  
  277. /******************************************************************/
  278. /* These string constants are used in multiple places, and thus   */
  279. /* save bytes by having only one copy of them.                    */
  280. /******************************************************************/
  281. char TITLETEXT[]        = "VirusX 3.20 by Steve Tibbett";
  282. char TDName[]           = "trackdisk.device";
  283. char copystring[]       = "(Copy Count on this disk: %ld)";
  284. char ITBodyText[80];
  285. char CaptureStr[]       = "Capture is pointing at $";
  286. char text[]             = "DF6: Boot Sectors";
  287. char VN_OBELISK[]       = "Obelisk";
  288. char VN_NORTHSTAR[]     = "North Star";
  289. char VN_SCA[]           = "SCA";
  290. char VN_BYTEBANDIT[]    = "Byte Bandit";
  291. char VN_BYTEWARRIOR[]   = "Byte Warrior";
  292. char VN_REVENGE[]       = "Revenge";
  293. char VN_IRQ[]           = "IRQ";
  294. char VN_PENTAGON[]      = "Pentagon Circle";
  295. char VN_LAMER[]        = "Lamer Exterminator";
  296. char VN_HCS[]        = "H.C.S.";
  297. char VN_UFOX[]        = "UltraFox";
  298. char VN_DDOC[]        = "DiskDoc";
  299. char VN_GRAFFITI[]    = "Graffiti";
  300. char VN_Bit16[]        = "16 Bit Crew";
  301. char VN_PHANTASM[]    = "Phantasmumble";    /* Can't remember the whole name */
  302. char VN_OLDNSTAR[]    = "Old Northstar";
  303.  
  304.  
  305. /********************************************************************/
  306. /* These counters are for the Info window, one for each virus.      */
  307. /********************************************************************/
  308. int     ObeliskCount;
  309. int     NorthStarCount;
  310. int     SCACount;
  311. int     ByteBanditCount;
  312. int     ByteWarriorCount;
  313. int     RevengeCount;
  314. int     IRQFound;
  315. int    PentagonCount;
  316. int     LamerXCount;
  317. int    HCSCount;
  318. int    UFoxCount;
  319. int    DDocCount;
  320. int    GRAFFITICount;
  321. int    Bit16Count;
  322. int    PhantasmCount;
  323. int     OldNStarCount;
  324.  
  325.  
  326. /*******************************************************************/
  327. /*  Miscellaneous variables.                                       */
  328. /*******************************************************************/
  329. long    ChangeCount[4];                 /* TD_CHANGECOUNT for 4 drives  */
  330. long    LastSum;                        /* Used in the checksumming     */
  331. long    error;                          /* sort of a temporary variable */
  332. char    WindowBig;                      /* TRUE if the window is big    */
  333. struct  Port *diskport;                 /* trackdisk's port.            */
  334. struct  IOStdReq *diskreq;              /* trackdisk's IOStdReq         */
  335. long    DisksChecked, DisksInstalled;   /* for title bar info           */
  336. long    VirusBase;                      /* ick, whatta name!            */
  337.  
  338. struct IntuitionBase    *IntuitionBase; /* For Library Bindings         */
  339. struct GfxBase          *GfxBase;
  340. struct Window           *Window;
  341. struct IntuiMessage     *Message;
  342. struct ExecBase         *ExecBase;
  343.  
  344. struct IOStdReq         *TimerReq;
  345. struct MsgPort          *TimerPort;
  346.  
  347. static long fp;
  348.  
  349. char Keepgoing;         /* A flag.  It's false when we want out.        */
  350. long x, y, i;           /* Left over from my using Basic                */
  351. char flag;              /* Another flag.  Lets start our own country.   */
  352. LONG thing1, thing2;
  353.  
  354. struct NewWindow NewWindow =
  355.         {
  356.         128,0,  309,10,  0,1,
  357.         DISKINSERTED | CLOSEWINDOW |VANILLAKEY | NEWSIZE | MOUSEBUTTONS,       /* IDCMP Flagz */
  358.         WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */
  359.         NULL, NULL,TITLETEXT,
  360.         NULL,NULL,0,0,0,0,WBENCHSCREEN,
  361.         };
  362.  
  363. struct RastPort *RP;
  364.  
  365. #define BSIZE 40        /* Ha!  I'm not telling what this is! */
  366.  
  367.  
  368. /*******************************************************************/
  369. /*  diskbuffer is where all disk io goes to.  it's 3*512 rather    */
  370. /*  than 2*512, because I believe one of the viruses watches for   */
  371. /*  reads of 1024 bytes, so I'm just being safe.                   */
  372. /*******************************************************************/
  373. UBYTE *diskbuffer;
  374.  
  375.  
  376. /************************************************************************/
  377. /* Warning messages.  These messages get modified before being          */
  378. /* displayed (Unless you DO have a DF9:)                                */
  379. /************************************************************************/
  380. char TEXTPTR[] = "Danger:  The disk in DF9: is";
  381. char NBCTEXT[] = "Danger:  The disk in DF9: has";  /* What a waste, eh? */
  382. char CopyText[40];
  383.  
  384. /*************************************************************************/
  385. /*   This is a byte by byte copy of working boot block code.  Check it   */
  386. /*   out if you like.  This is what gets written back to the disk when   */
  387. /*   you ask VirusX to fix a disk.                                       */
  388. /*************************************************************************/
  389. unsigned char bootblock[] = { 'D', 'O', 'S', 0,
  390. 0xc0, 0x20, 0x0f, 0x19, 0x00, 0x00, 0x03, 0x70, 0x43, 0xfa, 0x00, 0x18,
  391. 0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68,
  392. 0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 0x6f,
  393. 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
  394. 0x00, 0x00};
  395.  
  396.  
  397. /********************************************************************/
  398. /*  My intuition defines.  There's lots of 'em - theyre self explan.*/
  399. /********************************************************************/
  400.  
  401. struct TextAttr TxtAt_Plain =
  402.         {
  403.         "topaz.font", 8, FS_NORMAL, FPF_ROMFONT
  404.         };
  405.  
  406. /***  Non SCA warning requester IntuiText's ***/
  407.  
  408. struct IntuiText Body2 =
  409.         {
  410.         0, 1,  JAM2, 20,18, &TxtAt_Plain, "Nonstandard Boot Code!", NULL
  411.         };
  412.  
  413. struct IntuiText Body1 =
  414.         {
  415.         0,1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)NBCTEXT, &Body2
  416.         };
  417.  
  418. /*-  This one says "The disk in DFx: is"  -*/
  419.  
  420. struct IntuiText GenericFirstBody =
  421.         {
  422.         0,1, JAM2, 20,8,&TxtAt_Plain, (UBYTE *)TEXTPTR, 0
  423.         };
  424.  
  425.  
  426. /***** Generic IntuiTexts used as of V1.7 ******/
  427. struct IntuiText GenericDiskBody =
  428.         {
  429.         0,1, JAM2, 20,18, &TxtAt_Plain,ITBodyText, &GenericFirstBody
  430.         };
  431.  
  432. struct IntuiText SCAPos =
  433.         {
  434.         0,1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL
  435.         };
  436.  
  437. struct IntuiText Repair =
  438.         {
  439.         0,1, JAM2, 7,3, &TxtAt_Plain, "Repair it", NULL
  440.         };
  441.  
  442. struct IntuiText SCANeg =
  443.         {
  444.         0,1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL
  445.         };
  446.  
  447. /*  Special cases (display copy count) */
  448.  
  449. /***** BBANDIT Requester IntuiText's ******/
  450. struct IntuiText BBDiskbody2 =
  451.         {
  452.         0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
  453.         };
  454.  
  455. struct IntuiText BBDiskbody =
  456.         {
  457.         0,1, JAM2, 20,18, &TxtAt_Plain, ITBodyText, &BBDiskbody2
  458.         };
  459.  
  460. /***** Revenge on Disk Requester IntuiText's ******/
  461. struct IntuiText RevDiskbody3 =
  462.         {
  463.         0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
  464.         };
  465.  
  466. struct IntuiText RevDiskbody =
  467.         {
  468.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "infected with the -Revenge- VIRUS!", &RevDiskbody3
  469.         };
  470.  
  471.  
  472. /***** Generic Notice - Removed from Memory ****/
  473. struct IntuiText GRB3 =
  474.         {
  475.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "in memory, and is now disabled.  See the", NULL
  476.         };
  477.  
  478. struct IntuiText GRB2 =
  479.         {
  480.         0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "documentation for more information!", &GRB3
  481.         };
  482.  
  483. struct IntuiText GenericRAMBody =
  484.         {
  485.         0,1, JAM2, 20, 8, &TxtAt_Plain, ITBodyText, &GRB2
  486.         };
  487.  
  488. struct IntuiText BBMPos =
  489.         {
  490.         0,1, JAM2,  7, 3, &TxtAt_Plain, " Thanks! ", NULL
  491.         };
  492.  
  493. struct IntuiText Mem3 =
  494.         {
  495.         0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "some other utility is the cause of it.", NULL
  496.         };
  497.  
  498. struct IntuiText Mem2 =
  499.         {
  500.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "This could mean a new Virus is in RAM, or", &Mem3
  501.         };
  502.  
  503. struct IntuiText Mem1 =
  504.         {
  505.         0,1, JAM2, 20, 8, &TxtAt_Plain, 0 , &Mem2
  506.         };
  507.  
  508.  
  509. /***** Write Protect Error Requester IntuiText's ******/
  510. struct IntuiText ERRBody2 =
  511.         {
  512.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "Write Protected.", NULL
  513.         };
  514.  
  515. struct IntuiText ERRBody =
  516.         {
  517.         0,1, JAM2, 20,8, &TxtAt_Plain, (UBYTE *)"DISK ERROR:  Disk is", &ERRBody2
  518.         };
  519.  
  520. struct IntuiText ERRPos =
  521.         {
  522.         0,1, JAM2, 7,3, &TxtAt_Plain, "Retry", NULL
  523.         };
  524.  
  525. struct IntuiText ERRNeg =
  526.         {
  527.         0,1, JAM2, 7,3, &TxtAt_Plain, "Cancel", NULL
  528.         };
  529.  
  530.  
  531. /***** Rewrite block?  Really? ******/
  532. struct IntuiText REWBody3 =
  533.         {
  534.         0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "boot sectors?", NULL
  535.         };
  536.  
  537. struct IntuiText REWBody2 =
  538.         {
  539.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "rewrite that disk's boot", &REWBody3
  540.         };
  541.  
  542. struct IntuiText REWBody =
  543.         {
  544.         0,1, JAM2, 20,8, &TxtAt_Plain,      (UBYTE *)"Are you sure you want to", &REWBody2
  545.         };
  546.  
  547. struct IntuiText REWPos =
  548.         {
  549.         0,1, JAM2, 7,3, &TxtAt_Plain, "Yes", NULL
  550.         };
  551.  
  552. struct IntuiText REWNeg =
  553.         {
  554.         0,1, JAM2, 7,3, &TxtAt_Plain, "No!", NULL
  555.         };
  556.  
  557.  
  558. /*********************Da Beginnin*************************/
  559.  
  560. void main(argc, argv)
  561. int argc;
  562. char **argv;
  563. {
  564.  
  565. if (argc == 3)
  566.     {
  567.         NewWindow.LeftEdge = atoi(argv[1]);
  568.         NewWindow.TopEdge = atoi(argv[2]);
  569.         };
  570.  
  571. WindowBig = FALSE;
  572.  
  573. /* Come on, folks, is intuition ever NOT going to be available???? */
  574. IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L);
  575.  
  576. /* Same with GfxBase.  If GfxBase is gone, we DESERVE to crash. */
  577. GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
  578.  
  579. ExecBase = (struct ExecBase *)OpenLibrary("exec.library", 0);
  580.  
  581. diskbuffer = AllocMem((long)3*512, (long)MEMF_CHIP|MEMF_CLEAR);
  582. if (diskbuffer == 0)
  583.         {
  584.         /* Okay, okay, it's messy and doesn't close the libraries it
  585.            opens.  Look, if we can't get a measley 1.5K, then the
  586.            system is probably going to crash before the user finds out
  587.            what hit him, and he probably won't blame me.      */
  588.            exit(10);
  589.         };
  590.  
  591. /*  We use the same port/request through the whole program.  Works OK. */
  592. diskport = CreatePort(0L,0L);
  593. diskreq = CreateStdIO(diskport);
  594.  
  595. Window = OpenWindow(&NewWindow);
  596. if (Window == NULL)
  597.         goto Quitter;   /* No memory to open little window! */
  598.  
  599. RP = Window->RPort;
  600.  
  601. /* This does some setup stuff, I guess, eh? */
  602. SetUp();
  603.  
  604. /*  Check for Byte Bandit, SCA, Revenge and ByteWarrior, etc. in RAM.  */
  605. CheckMemoryForViruses();
  606.  
  607. /*  Hmmm, wonder what this does. */
  608. CheckMemoryForIRQVirus();
  609.  
  610. CheckBlock();
  611.  
  612. if (argc != 2)     /* New Feature:  Virusx CHECK will only check disks then quit */
  613.     DoLittle();     /* The main loop.  Do Little.  Ya. */
  614.  
  615. Quitter:
  616.  
  617. if (Window != 0) CloseWindow(Window);
  618.  
  619. if (diskport != 0) DeletePort(diskport);
  620. if (diskreq != 0) DeleteStdIO(diskreq);
  621.  
  622.  
  623. CloseLibrary(GfxBase);                                    /*
  624. CloseDoor(DoorBase);
  625. CloseLibrary(IntuitionBase);                                hahah bet I fooled you */  
  626. CloseLibrary((struct Library *)ExecBase);
  627. FreeMem(diskbuffer, (long)3*512);
  628. exit(0);
  629.  
  630. /* DoorBase?? */
  631. }
  632.  
  633. /*********************/
  634. DoLittle()
  635. {
  636. long Code;     /* for storing our IntuiMessage stuff */
  637. long Class;
  638. char KG2;      /* KeepGoing 2.  Another booleean. */
  639.  
  640. KG2 = TRUE;
  641.  
  642. SetAPen(RP, 1L);
  643. SetBPen(RP, 0L);
  644. SetDrMd(RP, (long)JAM2);
  645.  
  646. while (KG2 == TRUE)
  647.         {
  648.         Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
  649.         if (Message == 0)
  650.                 {
  651.                 CheckMemoryForIRQVirus();
  652.                 Delay(50);
  653.                 continue;
  654.                 };
  655.  
  656.         Class = Message->Class;
  657.         Code = Message->Code;
  658.         ReplyMsg((struct Message *)Message);
  659.  
  660.         if (Class == CLOSEWINDOW)
  661.                 {
  662.                 KG2 = FALSE;
  663.                 continue;
  664.                 };
  665.  
  666.         if (Class == MOUSEBUTTONS)
  667.                 if (Code == MENUDOWN)
  668.                         {
  669.                         Class = VANILLAKEY;
  670.                         Code = 'i';
  671.                         }
  672.                         else continue;
  673.  
  674.         if (Class == VANILLAKEY)
  675.                 {
  676.                 char flag;
  677.  
  678.                 switch (toupper(Code))
  679.                         {
  680.                         case 'I':
  681.                                 if (WindowBig == TRUE) WindowBig = FALSE;
  682.                                         else WindowBig = TRUE;
  683.  
  684.                                 if (WindowBig == TRUE)
  685.                                         {
  686.                                         if (Window->TopEdge > 0) MoveWindow(Window, 0L, (long)-Window->TopEdge);
  687.                                         SizeWindow(Window, 0L, 200-(Window->Height));
  688.                                         } else SizeWindow(Window, 0L, -Window->Height + 10);
  689.  
  690.                                 WaitForNewSize();
  691.                                 break;
  692.  
  693.  
  694.                         case 'C':
  695.                                 for (x=0; x<4; x++) ChangeCount[x] = 10000;
  696.                                 CheckBlock();
  697.  
  698.                         default:
  699.                                 flag = ShowAscii(Code);
  700.                                 if (flag == 1) CheckBlock();
  701.                         };
  702.                 if (WindowBig == TRUE) DoStats();
  703.                 };
  704.  
  705.         if (Class == DISKINSERTED)
  706.                 {
  707.                 CheckBlock();
  708.                 if (WindowBig == TRUE) DoStats();
  709.                 };
  710.         };
  711.  
  712. }
  713.  
  714.  
  715. /************************************************/
  716. /* Opens trackdisk, finds out who's out there,  */
  717. /* and sets Changecount up accordioningly.      */
  718. /************************************************/
  719. SetUp()
  720. {
  721. long x;
  722.  
  723. for (x = 0; x < 4; x++) /* go thru all 4 possible drives */
  724.         {
  725.         ChangeCount[x] = 1000;
  726.         error = OpenDevice(TDName,(long)x,diskreq,0L);
  727.         if (error > 0)
  728.                 {
  729.                 ChangeCount[x] = -1;
  730.                 } else CloseDevice(diskreq);
  731.         };
  732.  
  733. }
  734.  
  735. /*********************************************************/
  736. /* This routine returns which drive changed disks lately */
  737. /*********************************************************/
  738. WhoChanged()
  739. {
  740. char RetVal = -1;       /* The value we'll return */
  741.  
  742. for (x = 0; x < 4; x++)
  743.         {
  744.         if (ChangeCount[x] == -1)
  745.                 continue;       /* no drive here */
  746.         error = OpenDevice(TDName,(long)x,diskreq,(long)0);
  747.         if (error > 0)
  748.                 continue;       /* no drive here */
  749.  
  750.         diskreq->io_Command = TD_CHANGESTATE;
  751.         DoIO(diskreq);
  752.         if (diskreq->io_Actual != 0)
  753.                 {
  754.                 CloseDevice(diskreq);
  755.                 continue;
  756.                 };
  757.  
  758.         diskreq->io_Command = TD_CHANGENUM;
  759.         DoIO(diskreq);
  760.         if (diskreq->io_Actual != ChangeCount[x])
  761.                 {
  762.                 RetVal = x;
  763.                 ChangeCount[x] = diskreq->io_Actual;
  764.                 CloseDevice(diskreq);
  765.                 break;
  766.                 };
  767.  
  768.         CloseDevice(diskreq);
  769.         };
  770.  
  771. return(RetVal);
  772. }
  773.  
  774. /****************************************************************/
  775. /*  Figures out which drive changed disks (using WhoChanged(),  */
  776. /*  And checks it.  Calling this after every DISKINSERTED is OK.*/
  777. /****************************************************************/
  778. CheckBlock()
  779. {
  780. /*  How many register vars can I use, anyway? */
  781. register long Sum, Virus;
  782. register long a, Unit;
  783. char SCA, ByteWarrior, Revenge, BBandit;
  784. char NorthStar, Obelisk, Pentagon, LamerX, HCS;
  785. char DDoc, GRAFFITI, Bit16, Phantasm, OldNStar;
  786. char UFox;
  787. unsigned long *iptr;
  788. unsigned long *ptr;
  789. char drivename[10];
  790.  
  791. while ((Unit = WhoChanged()) != -1)
  792.         {
  793.         strcpy(drivename, "DF0:");
  794.         drivename[2] = '0'+Unit;
  795.  
  796.         SCA = FALSE;
  797.         BBandit = FALSE;
  798.         Revenge = FALSE;
  799.         ByteWarrior = FALSE;
  800.         NorthStar = FALSE;
  801.         Obelisk = FALSE;
  802.     Pentagon = FALSE;
  803.     LamerX = FALSE;
  804.     UFox = FALSE;
  805.     HCS = FALSE;
  806.     DDoc = GRAFFITI = Bit16 = Phantasm = OldNStar = FALSE;
  807.         
  808.         /* Unit # to open is returned by "WhoChanged()" up above. */
  809.         if (Unit == -1) return;
  810.         error = OpenDevice(TDName,(long)Unit,diskreq,0L);
  811.         if (error > 0) return;
  812.  
  813.         DisksChecked++;
  814.  
  815.         error = ReadBlock();
  816.         CloseDevice(diskreq);
  817.         if (error == FALSE) return;
  818.  
  819.         ptr = (long *)diskbuffer;
  820.         iptr = (long *)diskbuffer;
  821.  
  822.         if (iptr[0] != ID_DOS_DISK) return;     /* No DOS/0 */
  823.     
  824.         Sum = 0;
  825.         for (a=0; a<256; a++)
  826.                 {
  827.                 LastSum = Sum;
  828.                 Sum = Sum + ptr[a];
  829.                 if (LastSum > Sum) Sum++;  /* took me a while to figger this out */
  830.                 }
  831.  
  832.         if (Sum != 0)
  833.                 {
  834.                 CheckDriveForIRQ(drivename);
  835.                 return; /* if it's not bootable, we DONT want it! */
  836.                 };
  837.  
  838.         if (diskbuffer[0x40] == 0xff)
  839.                 if (diskbuffer[0x41] == 0xa0)
  840.                         if (diskbuffer[0x42] == 0x20)
  841.                                 if (diskbuffer[0x43] == 0x40)
  842.         {
  843.         PentagonCount++;
  844.         Pentagon = TRUE;
  845.         }
  846.  
  847.         if (iptr[0x40/4] == 0x13fc00a0)
  848.         {
  849.         DDocCount++;
  850.         DDoc = TRUE;
  851.         }
  852.  
  853.         if (iptr[0x150/4] == 0x000100bf)
  854.         {
  855.         GRAFFITICount++;
  856.         GRAFFITI = TRUE;
  857.         }
  858.  
  859.         if (iptr[0x150/4] == 0x3fff2c78)
  860.         {
  861.         Bit16Count++;
  862.         Bit16 = TRUE;
  863.         }
  864.  
  865.         if (iptr[0x40/4] == 0x4240323c)
  866.         {
  867.         PhantasmCount++;
  868.         Phantasm = TRUE;
  869.         }
  870.  
  871.         if (iptr[0x40/4] == 0x0007ec1a)
  872.         {
  873.         OldNStarCount++;
  874.         OldNStar = TRUE;
  875.         }
  876.  
  877.         if (iptr[0x1d0/4] == 0x83353ef0)
  878.         /*
  879.         diskbuffer[0x1d0] == 0x83)
  880.                 if (diskbuffer[0x1d1] == 0x35)
  881.                         if (diskbuffer[0x1d2] == 0x3e)
  882.                                 if (diskbuffer[0x1d3] == 0xf0)
  883.     */
  884.         {
  885.         UFoxCount++;
  886.         UFox = TRUE;
  887.         }
  888.  
  889.         if (diskbuffer[0x40] == 0x51)
  890.                 if (diskbuffer[0x41] == 0xc8)
  891.                         if (diskbuffer[0x42] == 0xff)
  892.                                 if (diskbuffer[0x43] == 0xfc)
  893.         {
  894.         HCSCount++;
  895.         HCS = TRUE;
  896.         }
  897.  
  898.         if (diskbuffer[0x40] == 0x03)
  899.                 if (diskbuffer[0x41] == 0x61)
  900.                         if (diskbuffer[0x42] == 0x34)
  901.                                 if (diskbuffer[0x43] == 0x3c)
  902.         {
  903.         LamerXCount++;
  904.         LamerX = TRUE;
  905.         }
  906.                     
  907.        if (diskbuffer[0x34] == 100)
  908.                 if (diskbuffer[0xc4] == 48)
  909.                         if (diskbuffer[0xc0] == 68)
  910.                                 if (diskbuffer[0xf1] == 7)
  911.                                         {
  912.                                         ByteWarriorCount++;
  913.                                         ByteWarrior = TRUE;
  914.                                         };
  915.  
  916.         if (diskbuffer[0x2b] == '9')
  917.                 if (diskbuffer[0x2c] == '.')
  918.                         if (diskbuffer[0x2d] == '8')
  919.                                 if (diskbuffer[0x2e] == '7')
  920.                                         {
  921.                                         ByteBanditCount++;
  922.                                         BBandit = TRUE; /* 9.87 is part of BBandit Virus */
  923.                                         };
  924.  
  925.         /* check specifically for SCA virus */
  926.         if (diskbuffer[0x149] == 0x28)
  927.                 if (diskbuffer[0x14a] == 0x23)
  928.                         if (diskbuffer[0x14b] == 0x7c)
  929.                                         {
  930.                                         SCA = TRUE;     /* CHW is part of SCA virus */
  931.                                         SCACount++;
  932.                                         };
  933.  
  934.         if (diskbuffer[0xe] == 'I')
  935.                 if (diskbuffer[0xf] == 'D')
  936.                         if (diskbuffer[0x10] == '9')
  937.                                 if (diskbuffer[0x1a6] == 'f')
  938.                                         {
  939.                                         Revenge= TRUE;
  940.                                         RevengeCount++;
  941.                                         };
  942.  
  943.         if (diskbuffer[0x12] == 78)
  944.                 if (diskbuffer[0x13c] == 68)
  945.                         if (diskbuffer[0x18] == 83)
  946.                                 if (diskbuffer[0x19] == 116)
  947.                                         {
  948.                                         NorthStar = TRUE;
  949.                                         NorthStarCount++;
  950.                                         };
  951.  
  952.  
  953.         if (diskbuffer[0x38] == 71)
  954.                 if (diskbuffer[0xbc] == 83)
  955.                         if (diskbuffer[0x1fb] == 100)
  956.                                 if (diskbuffer[0x2d] == 80)
  957.                                         {
  958.                                         Obelisk = TRUE;
  959.                                         ObeliskCount++;
  960.                                         };
  961.  
  962.         /* compare boot block with real boot block.  If it's not, notify God. */
  963.         Virus = FALSE;
  964.  
  965.         for (x = 0; x < 39; x++) /* num of bytes in bootblock */
  966.                 {
  967.                 if (diskbuffer[8+x] != bootblock[8+x])
  968.                         {
  969.                         Virus = TRUE;
  970.                         };
  971.                 };
  972.  
  973.         /* Oh no, a Virus! */
  974.         if (Virus == TRUE)
  975.                 {
  976.                 NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
  977.                 TEXTPTR[23] = '0'+Unit;
  978.                 error = FALSE;
  979.  
  980.                 if (SCA == TRUE)
  981.                         {
  982.                         /* OH NOOOOO, an SCA virus.  Wimpo virus, compared to BBandit
  983.                            but it's a lot nicer code to read. */
  984.                         error = MyRequest(VN_SCA, 1);
  985.                         }
  986.                 else if (BBandit == TRUE)
  987.                         {
  988.                         /* The Byte Bandit Virus.  Tricky bugger, he WAS. Cheats, tho. */
  989.                         sprintf(CopyText, copystring, (long)(diskbuffer[74]*256)+diskbuffer[75]);
  990.                         BuildITBodyText(VN_BYTEBANDIT, 1);
  991.                         error = AutoRequest(Window, &BBDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
  992.                         }
  993.                 else if (Revenge == TRUE)
  994.                         {
  995.                         /* Revenge virus.  X rated bugger, lot like Byte Bandit. */
  996.                         sprintf(CopyText, copystring, (long)(diskbuffer[0x3f6]*256)+diskbuffer[0x3f7]);
  997.                         BuildITBodyText(VN_REVENGE, 1);
  998.                         error = AutoRequest(Window, &RevDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
  999.                         }
  1000.                 else if (ByteWarrior == TRUE)
  1001.                         {
  1002.                         /* Byte Warrior.  Very 'friendly' virus.  Ez to get rid of.  */
  1003.                         error = MyRequest(VN_BYTEWARRIOR, 1);
  1004.                         }
  1005.                 else if (Pentagon == TRUE)
  1006.                         {
  1007.                         /* Pentagon Circle.  An 'AntiVirus', and not a bad one at that. */
  1008.                         error = MyRequest(VN_PENTAGON, 1);
  1009.                         }
  1010.                 else if (NorthStar == TRUE)
  1011.                         {
  1012.                         /* NorthStar.  Nice virus - alerts you to others, ez to get rid of */
  1013.                         error = MyRequest(VN_NORTHSTAR, 1);
  1014.                         }
  1015.                 else if (Obelisk == TRUE)
  1016.                         {
  1017.                         /* At least these guys are getting creative with their Graphics! */
  1018.                         error = MyRequest(VN_OBELISK, 1);
  1019.                         }
  1020.                 else if (LamerX == TRUE)
  1021.                         {
  1022.                         /* At least these guys are getting creative with their Graphics! */
  1023.                         error = MyRequest(VN_LAMER, 1);
  1024.                         }
  1025.                 else if (HCS == TRUE)
  1026.                         {
  1027.                         /* At least these guys are getting creative with their Graphics! */
  1028.                         error = MyRequest(VN_HCS, 1);
  1029.                         }
  1030.                 else if (UFox == TRUE)
  1031.                         {
  1032.                         /* yawn */
  1033.                         error = MyRequest(VN_UFOX, 1);
  1034.                         }
  1035.                 else if (DDoc == TRUE)
  1036.                         {
  1037.                         /* yawn */
  1038.                         error = MyRequest(VN_DDOC, 1);
  1039.                         }
  1040.                 else if (GRAFFITI == TRUE)
  1041.                         {
  1042.                         /* yawn */
  1043.                         error = MyRequest(VN_GRAFFITI, 1);
  1044.                         }
  1045.                 else if (Bit16 == TRUE)
  1046.                         {
  1047.                         /* yawn */
  1048.                         error = MyRequest(VN_Bit16, 1);
  1049.                         }
  1050.                 else if (Phantasm == TRUE)
  1051.                         {
  1052.                         /* yawn */
  1053.                         error = MyRequest(VN_PHANTASM, 1);
  1054.                         }
  1055.                 else if (OldNStar == TRUE)
  1056.                         {
  1057.                         /* yawn */
  1058.                         error = MyRequest(VN_OLDNSTAR, 1);
  1059.                         }
  1060.                 else
  1061.                         {
  1062.                         /* Probably just a custom boot block (or a new virus...) */
  1063.                         error = AutoRequest(Window, &Body1, &SCAPos, &SCANeg, 0L, 0L, 320L, 70L);
  1064.                         }
  1065.                 if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */
  1066.                 };
  1067.         CheckDriveForIRQ(drivename);
  1068.         };  /* End of While Whochanged */
  1069.  
  1070. }
  1071.  
  1072. /********************************************/
  1073. /* This is where the boot code gets changed */
  1074. /********************************************/
  1075. DoInstall(un)
  1076. int un; /* unit to write to */
  1077. {
  1078. register int x;
  1079.  
  1080. /* Rewrite disk?  Really?  */
  1081. error = AutoRequest(Window, &REWBody, &REWPos, &REWNeg, 0L, 0L, 320L, 75L);
  1082. if (error != TRUE) return;      /* user changed his brain. */
  1083.  
  1084. DisksInstalled++;
  1085.  
  1086. error = OpenDevice(TDName, (long)un,diskreq,0L);
  1087. if (error > 0) return;
  1088.  
  1089. TryGain:
  1090.  
  1091.         diskreq->io_Command = TD_PROTSTATUS;
  1092.         DoIO(diskreq);          /* check if disk is write protected */
  1093.  
  1094.         if (diskreq->io_Actual != 0)
  1095.                 {
  1096.                 error = AutoRequest(Window, &ERRBody, &ERRPos, &ERRNeg, 0L, 0L, 280L, 75L);
  1097.                 if (error == TRUE) /* error is true or false, depending on user */
  1098.                         {
  1099.             goto TryGain;
  1100.                         };
  1101.             CloseDevice(diskreq);
  1102.             return; /* unrecoverable write protect error!! Panic!!!!!!! */
  1103.         };
  1104.  
  1105. for (x = 0; x < 1024; x++)
  1106.         diskbuffer[x] = 0;      /* clear diskbuffer to zero.  clean. */
  1107.  
  1108. CopyMem(bootblock, diskbuffer, 50L); /* Copy it over */
  1109.  
  1110. /* Write it ! */
  1111.  
  1112.         error = 0;
  1113.         diskreq->io_Length = 1024; /* here we go! */
  1114.         diskreq->io_Data = (APTR)diskbuffer;
  1115.         diskreq->io_Command = CMD_WRITE;
  1116.         diskreq->io_Offset = 0L;
  1117.         DoIO(diskreq);
  1118.         error = diskreq->io_Error;
  1119.  
  1120. if (error < 19)
  1121.         {
  1122.         diskreq->io_Command = CMD_UPDATE;       /* flush buffer to disk */
  1123.         DoIO(diskreq);
  1124.         error = diskreq->io_Error;
  1125.         };
  1126.  
  1127. if (error < 19)
  1128.         {
  1129.         diskreq->io_Length = 0;
  1130.         diskreq->io_Command = ETD_MOTOR;
  1131.         DoIO(diskreq);                          /* turn off motor */
  1132.         error = diskreq->io_Error;
  1133.         };
  1134.  
  1135. CloseDevice(diskreq);
  1136.  
  1137. if (error > 19)
  1138.         {
  1139.         SetWindowTitles(Window, "Disk Error!", (STRPTR)-1);
  1140.         }
  1141.     else
  1142.         {
  1143.         SetWindowTitles(Window, "Disk Healed.", (STRPTR)-1);
  1144.         };
  1145.  
  1146. Delay(150L);
  1147. SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
  1148. }
  1149.  
  1150.  
  1151. /************************/
  1152.  
  1153. CheckMemoryForViruses()
  1154. {
  1155. unsigned long *TD;
  1156. unsigned short *wordpointer;
  1157. unsigned long *LongMemPointer;  /* Used for reading FROM memory */
  1158. unsigned long *ptr;
  1159. char linebuffer[80];
  1160. char *charpointer;
  1161. unsigned int x;
  1162.  
  1163. /**************- Check for Byte Bandit (look at TD Vector) *************/
  1164. /*  (Byte Bandit isn't at a fixed location.  Depends on your RAM.      */
  1165.  
  1166. /* LongMemPointer = &trackdisk.device */
  1167. TD = (unsigned long *)FindName(&ExecBase->DeviceList, TDName);
  1168.  
  1169. x = (unsigned int) TD;
  1170. x = x - 0x1c;
  1171. ptr = (unsigned long *) x;
  1172. LongMemPointer = (unsigned long *) *ptr;
  1173. x = (unsigned int) LongMemPointer;
  1174. x = x - 0x1b8;
  1175. LongMemPointer = (unsigned long *) x;
  1176.  
  1177. if (*LongMemPointer == ID_DOS_DISK)     /* klugo */
  1178.            {
  1179.         /* Ok, so we don't really remove it from memory, but we DO render
  1180.               it harmless. */
  1181.         Disable();
  1182.            charpointer = (char *)VirusBase;
  1183.         charpointer[0xaa] = 0x4e;
  1184.            charpointer[0xac] = 0x4e;
  1185.         charpointer[0xae] = 0x4e;
  1186.            charpointer[0xb0] = 0x4e;
  1187.         charpointer[0xab] = 0x71;
  1188.            charpointer[0xad] = 0x71;
  1189.         charpointer[0xaf] = 0x71;    /* Isn't this code terrible?  Ick! */
  1190.            charpointer[0xb1] = 0x71;    /* I didn't know what I was doing when */
  1191.         charpointer[0x1c2] = 0x60;   /* I wrote this.  (excuses... 8-)  */
  1192.            charpointer[0x1c3] = 0;
  1193.         charpointer[0x2d2] = 0x60;
  1194.            charpointer[0x2d3] = 0;
  1195.         charpointer[0x388] = 0x4e;
  1196.            charpointer[0x389] = 0x75;
  1197.         charpointer[0x3ea] = 0;
  1198.            charpointer[0x3eb] = 0;
  1199.         charpointer[0] = 0;
  1200.            Enable();
  1201.  
  1202.         MyRequest(VN_BYTEBANDIT, 2);
  1203.            };
  1204.     
  1205.  
  1206. TD = (unsigned long *)FindName(&ExecBase->DeviceList, TDName);
  1207. x = (unsigned int) TD;
  1208. x = x - 0x1c;
  1209. LongMemPointer = (unsigned long *)x;
  1210. LongMemPointer = (unsigned long *)LongMemPointer[0];
  1211. x = (unsigned int)LongMemPointer;
  1212. x = x - 0x17c;
  1213. LongMemPointer = (unsigned long *)x;
  1214.  
  1215. if (*LongMemPointer == ID_DOS_DISK)    /* ptr == VirusBase */
  1216.     {
  1217.     char *a;
  1218.     long *src, *dest;
  1219.     long *vbase;
  1220.     
  1221.     *LongMemPointer = 0;    /* Kill DOS\0 */
  1222.  
  1223.     vbase = LongMemPointer;
  1224.     
  1225.     /* Disable, then repair vectors. */
  1226.     Disable();
  1227.  
  1228.     /* addr of real TD vector */
  1229.     src = &vbase[0x3a8/4];
  1230.     a = (char *)ExecBase;
  1231.     a = a - 0x264;
  1232.     dest = (unsigned long *)a;
  1233.     *dest = *src;
  1234.     
  1235.     src = (unsigned long *) &vbase[0x3ac/4];
  1236.     a = (char *)TD;
  1237.     a = a - 0x1c;
  1238.     dest = (unsigned long *)a;
  1239.     *dest = *src;
  1240.     
  1241.     Enable();
  1242.     
  1243.     ExecBase->KickTagPtr = 0;    /* Sorry, I know it's cruel */
  1244.  
  1245.         MyRequest(VN_LAMER, 2);
  1246.  
  1247.     }
  1248.  
  1249.     
  1250.  
  1251.  
  1252. /****************- Look for Revenge Virus (at $7e000) ****************/
  1253. if ((unsigned long)ExecBase->CoolCapture == (unsigned long)516192)
  1254.         {
  1255.         /* Fix the CoolCapture vector */
  1256.         ExecBase->CoolCapture = 0;
  1257.  
  1258.         Disable();
  1259.  
  1260.         wordpointer = (unsigned short *)(0x7e000);
  1261.         wordpointer[0] = 0;
  1262.  
  1263.         wordpointer = (unsigned short *)(0x7e000+0x1e0);
  1264.         wordpointer[0] = 0x4ef9;
  1265.         wordpointer[1] = 0x0007;
  1266.         wordpointer[2] = 0xe066;
  1267.  
  1268.         wordpointer = (unsigned short *)0x7e2da;
  1269.         wordpointer[0] = 0x4ef9;
  1270.         wordpointer[1] = 0x0007;
  1271.         wordpointer[2] = 0xe06c;
  1272.  
  1273.         Enable();
  1274.  
  1275.         MyRequest(VN_REVENGE, 2);
  1276.         };
  1277.  
  1278. /******************** See if SCA is in RAM ***************************/
  1279. if ((long)ExecBase->CoolCapture == (long)0x7ec3e)
  1280.         {
  1281.         ExecBase->CoolCapture = 0;
  1282.         MyRequest(VN_SCA, 2);
  1283.         };
  1284.  
  1285. /******************** See if Graffiti is in RAM ***************************/
  1286. if ((long)ExecBase->CoolCapture == (long)0x7ec58)
  1287.         {
  1288.         ExecBase->CoolCapture = 0;
  1289.         MyRequest(VN_GRAFFITI, 2);
  1290.         };
  1291.  
  1292. /******************** How about Phantasmumble? ***************************/
  1293. if ((long)ExecBase->CoolCapture == (long)0x7ec74)
  1294.         {
  1295.         ExecBase->CoolCapture = 0;
  1296.         MyRequest(VN_PHANTASM, 2);
  1297.         };
  1298.  
  1299. /******************** Yoo hoo?  HCS?  Are you here? ******************/
  1300. if ((long)ExecBase->CoolCapture == (long)0x7ec64)
  1301.         {
  1302.         /* You are, you little dickens.  */
  1303.         
  1304.         ExecBase->CoolCapture = 0;
  1305.     
  1306.     /* Scat! */
  1307.     
  1308.     x = (unsigned int) ExecBase;
  1309.     x = x - 0x1c6;
  1310.     ptr = (unsigned long *)x;
  1311.     
  1312.     LongMemPointer = (unsigned long *)0x7ef9c;
  1313.     
  1314.     *ptr = *LongMemPointer;    /* un-Step on DoIO() vector */
  1315.  
  1316.         MyRequest(VN_HCS, 2);
  1317.         };
  1318.  
  1319. /**************************** DiskDoktor? ****************************/
  1320. wordpointer = ExecBase->CoolCapture;
  1321. if (*wordpointer == 0x2c79)
  1322.     {
  1323.     if (wordpointer[3] == 0x203c)
  1324.         {
  1325.         int x;
  1326.         
  1327.         Disable();
  1328.         
  1329.         x = ExecBase;
  1330.         x = x - 0x1c6;
  1331.         LongMemPointer = (long *)x;
  1332.         
  1333.         wordpointer = (UWORD *)*LongMemPointer;
  1334.  
  1335.         x = (int)wordpointer;
  1336.         x = x + (0x15c);
  1337.         wordpointer = (UWORD *)x;
  1338.         *wordpointer = 0x4e75;
  1339.  
  1340.         x = (int)wordpointer;
  1341.         x = x + 0x1e2;
  1342.         wordpointer = (UWORD *)x;
  1343.         *wordpointer = 0x4e75;
  1344.         
  1345.          x = (int)ExecBase;
  1346.         x = x - 0x1c6;
  1347.         ptr = (long *)x;
  1348.         
  1349.         x = (int)*ptr;
  1350.         x = x + 2;
  1351.         LongMemPointer = (long *)x;
  1352.                 
  1353.         *ptr = *LongMemPointer;
  1354.  
  1355.         ExecBase->CoolCapture = 0;
  1356.         ExecBase->ColdCapture = 0;
  1357.         ExecBase->WarmCapture = 0;
  1358.  
  1359.         Enable();
  1360.         
  1361.         MyRequest(VN_DDOC, 2);
  1362.         };
  1363.     };
  1364.  
  1365.  
  1366. /******************** It's the Australian UltraFox  ******************/
  1367. if ((long)ExecBase->CoolCapture == (long)0x7ed36)
  1368.         {
  1369.         UWORD *wordptr;
  1370.  
  1371.      ExecBase->CoolCapture = 0;
  1372.     
  1373.     x = (unsigned int) ExecBase;
  1374.     x = x - 0x1c6;
  1375.     ptr = (unsigned long *)x;
  1376.     wordptr = (UWORD *)ptr;
  1377.     if (wordptr[0] == 0x0007)
  1378.         {
  1379.         LongMemPointer = (unsigned long *)0x7eb38;
  1380.         *ptr = *LongMemPointer;    /* un-Step on DoIO() vector */
  1381.         };
  1382.         
  1383.         MyRequest(VN_UFOX, 2);
  1384.         };
  1385.  
  1386. /***************** Check for Obelisk  *******************************/
  1387. if ((APTR)ExecBase->CoolCapture == (APTR)0x7e86c)
  1388.         {
  1389.         ExecBase->CoolCapture = 0;
  1390.         ptr = (unsigned long *)0x7e88a;
  1391.         Forbid();
  1392.         ptr[0] = 10;
  1393.         Permit();
  1394.         MyRequest(VN_OBELISK, 2);
  1395.         };
  1396.  
  1397. /******************** How about North Star? **************************/
  1398. if ((APTR)ExecBase->CoolCapture == (APTR)0x7ec0e)
  1399.         {
  1400.         ExecBase->CoolCapture = 0;
  1401.         MyRequest(VN_NORTHSTAR, 2);
  1402.         };
  1403.  
  1404. /********************* Check for Byte Warrior ************************/
  1405. wordpointer = (unsigned short *)0x7f800;
  1406. if ( wordpointer[0] == (0x444f) )
  1407.         {
  1408.         wordpointer = (unsigned short *)0x7f954;
  1409.         if (wordpointer[0] == 0x4afc)
  1410.                 {
  1411.                 wordpointer[0] = 0;             /* Kill resident matchtag */
  1412.  
  1413.                 Forbid();
  1414.  
  1415.                 wordpointer = (unsigned short *)0x7f972;
  1416.                 wordpointer[0] = 0x4ef9;
  1417.                 wordpointer[1] = 0x00fc;
  1418.                 wordpointer[2] = 0x06dc;
  1419.  
  1420.                 wordpointer =  (unsigned short *)0x7f800;
  1421.                 wordpointer[0] = 0;
  1422.  
  1423.                 Permit();
  1424.  
  1425.                 MyRequest(VN_BYTEWARRIOR, 2);
  1426.                 };
  1427.         };
  1428.  
  1429. /******************** See if Pentagon is in RAM ***************************/
  1430. if ((long)ExecBase->CoolCapture == (long)0x7fb4c)
  1431.         {
  1432.         ExecBase->CoolCapture = 0;
  1433.  
  1434.         /* He sometimes has the DoIO() setfunctioned, I can't figure out
  1435.            when, but even if he does, he doesn't do any harm anyway, and
  1436.            with CoolCapture set to 0, he'll be gone at next reboot.  */
  1437.            
  1438.         MyRequest(VN_PENTAGON, 2);
  1439.     };
  1440.     
  1441.  
  1442. if (ExecBase->CoolCapture != 0)
  1443.         {
  1444.         sprintf(linebuffer, "Cool%s%lx", CaptureStr, ExecBase->CoolCapture);
  1445.         if (MyRequest(linebuffer, 3) == TRUE) ExecBase->CoolCapture = 0;
  1446.         }
  1447.  
  1448. if (ExecBase->ColdCapture != 0)
  1449.         {
  1450.         sprintf(linebuffer, "Cold%s%lx", CaptureStr, ExecBase->ColdCapture);
  1451.         if (MyRequest(linebuffer, 3) == TRUE) ExecBase->ColdCapture = 0;
  1452.         }
  1453.  
  1454. if (ExecBase->WarmCapture != 0)
  1455.         {
  1456.         sprintf(linebuffer, "Warm%s%lx", CaptureStr, ExecBase->WarmCapture);
  1457.         if (MyRequest(linebuffer, 3) == TRUE) ExecBase->WarmCapture = 0;
  1458.         }
  1459. }
  1460.  
  1461.  
  1462. /**************************************************************/
  1463. /*  This is the routine that displauys a block as ASCII text. */
  1464. /**************************************************************/
  1465. ShowAscii(key)
  1466. long key;
  1467. {
  1468. int drive;
  1469. int x,y;
  1470. int deltax, deltay;
  1471. long a;
  1472. int FLAG=0;
  1473.  
  1474. struct RastPort *RP;
  1475. RP = Window->RPort;
  1476.  
  1477. drive = key - '0';
  1478.  
  1479. if ((drive < 0) || (drive > 3) || (ChangeCount[drive] == -1)) return;
  1480.  
  1481. error = OpenDevice(TDName,(long)drive,diskreq,0L);
  1482. if (error > 0) return;
  1483.  
  1484. error = ReadBlock();
  1485.  
  1486. CloseDevice(diskreq);
  1487.  
  1488. if (error == FALSE) return;
  1489.  
  1490. /* save the amount we moved the window */
  1491. deltax = Window->LeftEdge;
  1492. deltay = Window->TopEdge;
  1493.  
  1494. MoveWindow(Window, -deltax, -deltay);
  1495.  
  1496. if (WindowBig == FALSE) SizeWindow(Window, 278L, 160L);
  1497.         else SizeWindow(Window, 278L, 0L);
  1498.  
  1499. WaitForNewSize();
  1500.  
  1501. SetAPen(RP, 0L);
  1502. RectFill(RP, 2, 12, 278, 167);
  1503.  
  1504. SetAPen(RP, 3L);
  1505. Move(RP, (long)(14+(12*8)), 165L);
  1506. Text(RP, "Block 0", 7L);
  1507. Move(RP, (long)(324+(12*8)), 165L);
  1508. Text(RP, "Block 1", 7L);
  1509. SetAPen(RP, 1L);
  1510.  
  1511. text[2] = key;
  1512. SetWindowTitles(Window, text, (STRPTR)-1);
  1513.  
  1514. x=0; y=0;
  1515.  
  1516. SetAPen(RP, 1L);
  1517. SetDrMd(RP, JAM2);
  1518.  
  1519. for (a=0; a<512; a=a+32)
  1520.         {
  1521.         Move(RP, (long)(10+(x*8)), (long)20+(y*9));
  1522.         Text(RP, &diskbuffer[a], 32L);
  1523.  
  1524.         Move(RP, (long)(320+(x*8)), (long)20+(y*9));
  1525.         Text(RP, &diskbuffer[a+512], 32L);
  1526.         y++;
  1527.         };
  1528.  
  1529. Wait(1<<Window->UserPort->mp_SigBit);
  1530. Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
  1531.  
  1532. /*  If a disk was inserted, we want CheckBlock() to happen later on some time */
  1533. if (Message->Class == DISKINSERTED) FLAG=1;
  1534. ReplyMsg((struct Message *)Message);
  1535.  
  1536. if (WindowBig == FALSE)
  1537.         SizeWindow(Window, -278L, -160L);
  1538.         else SizeWindow(Window, -278L, 0L);
  1539.  
  1540. SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
  1541. WaitForNewSize();
  1542.  
  1543. /* deltas plus current position, in case dude moved the window */
  1544. MoveWindow(Window, deltax+(-Window->LeftEdge), deltay+(-Window->TopEdge));
  1545. Delay(2L);
  1546. return(FLAG);
  1547. }
  1548.  
  1549.  
  1550. /*
  1551.  When you do a SizeWindow() command, you have to wait for a NEWSIZE
  1552.  IntuiMessage before drawing in it.  That's all this routine does.
  1553.  */
  1554. WaitForNewSize()
  1555. {
  1556. while (TRUE)
  1557.         {
  1558.         WaitPort(Window->UserPort);
  1559.         Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
  1560.         if (Message->Class != NEWSIZE)
  1561.                 {
  1562.                 ReplyMsg((struct Message *)Message);
  1563.                 continue;
  1564.                 };
  1565.         ReplyMsg((struct Message *)Message);
  1566.         break;
  1567.         };
  1568. }
  1569.  
  1570. /*
  1571.         type:
  1572.  
  1573.                 1 == "is infected with the xxxx VIRUS!"
  1574.                 2 == "somethin about virus in ram"
  1575.                 3 == virus in cold/cool/warm capture
  1576. */
  1577.  
  1578. BuildITBodyText(text, type)
  1579. char *text;
  1580. int type;
  1581. {
  1582. switch (type)
  1583.         {
  1584.         case 1:
  1585.                 strcpy(ITBodyText, "infected with the `");
  1586.                 strcat(ITBodyText, text);
  1587.                 strcat(ITBodyText, "' VIRUS!");
  1588.                 break;
  1589.         case 2:
  1590.                 strcpy(ITBodyText, "NOTICE:  The `");
  1591.                 strcat(ITBodyText, text);
  1592.                 strcat(ITBodyText, "' VIRUS was found");
  1593.                 break;
  1594.         };
  1595. }
  1596.  
  1597. /***** an attempt to save space *********/
  1598. MyRequest(string, type)
  1599. char *string;
  1600. int type;
  1601. {
  1602. if (type != 3)
  1603.         {
  1604.         BuildITBodyText(string, type);
  1605.         } else
  1606.         {
  1607.         Mem1.IText = string;
  1608.         };
  1609.  
  1610. if (type == 1) return(AutoRequest(Window, &GenericDiskBody, &SCAPos, &SCANeg, 0L, 0L, 420L, 80L));
  1611. if (type == 2) return(AutoRequest(Window, &GenericRAMBody, &BBMPos, &BBMPos, 0L, 0L, 420L, 78L));
  1612. if (type == 3) return(AutoRequest(Window, &Mem1, &Repair, &SCANeg, 0L, 0L, 420L, 78L));
  1613. }
  1614.  
  1615.  
  1616. /********* DoStats() **********/
  1617. DoStats()
  1618. {
  1619. char linebuffer[80];
  1620.  
  1621. SetAPen(RP, 0L);
  1622. RectFill(RP, 2L, 11L, 303L, Window->Height-13);
  1623. SetAPen(RP, 1L);
  1624.  
  1625. sprintf(linebuffer, "  Disks Checked: %ld", DisksChecked);
  1626. Out(20, linebuffer);
  1627.  
  1628. sprintf(linebuffer, "Disks Installed: %ld", DisksInstalled);
  1629. Out(29, linebuffer);
  1630.  
  1631. Out(43, "    Viruses Found:");
  1632.  
  1633. PV(52, VN_SCA, SCACount);
  1634. PV(61, VN_BYTEBANDIT, ByteBanditCount);
  1635. PV(70, VN_NORTHSTAR, NorthStarCount);
  1636. PV(79, VN_BYTEWARRIOR, ByteWarriorCount);
  1637. PV(88, VN_REVENGE, RevengeCount);
  1638. PV(97, VN_OBELISK, ObeliskCount);
  1639. PV(106, VN_IRQ, IRQFound);
  1640. PV(115, VN_PENTAGON, PentagonCount);
  1641. PV(124, VN_HCS, HCSCount);
  1642. PV(133, VN_DDOC, DDocCount);
  1643. PV(142, VN_GRAFFITI, GRAFFITICount);
  1644. PV(151, VN_Bit16, Bit16Count);
  1645. PV(160, VN_PHANTASM, PhantasmCount);
  1646. PV(169, VN_OLDNSTAR, OldNStarCount);
  1647. PV(178, VN_UFOX, UFoxCount);
  1648. PV(187, VN_LAMER, LamerXCount);
  1649. }
  1650.  
  1651. /****************** Ok, we're REALLY being chintzy here. */
  1652. PV(num, name, howmany)
  1653. int num;
  1654. char *name;
  1655. int howmany;
  1656. {
  1657. char linebuffer[80];
  1658.  
  1659. sprintf(linebuffer, "%-19s: %ld", name, howmany);
  1660. Out(num, linebuffer);
  1661. }
  1662.  
  1663. /***************************************** Cheap?  Me?  Nooooo....     */
  1664. /* This will write text to the column number in NUM, the text in Name. */
  1665. /*  Or something like that. ********************************************/
  1666. Out(num, name)
  1667. int num;
  1668. char *name;
  1669. {
  1670. int len;
  1671. len = 0;
  1672.  
  1673. while (name[len] != 0) len++;
  1674.  
  1675. Move(RP, 20L, (long)num);
  1676. Text(RP, name, len);
  1677. }
  1678.  
  1679.  
  1680. ReadBlock()
  1681. {
  1682. diskreq->io_Command = CMD_READ;
  1683. diskreq->io_Data = (APTR)diskbuffer;
  1684. diskreq->io_Length = 3*512;
  1685. diskreq->io_Offset = 0;
  1686. DoIO(diskreq);
  1687. if (diskreq->io_Error > 0) return(FALSE);
  1688. diskreq->io_Length = 0;
  1689. diskreq->io_Command = TD_MOTOR;
  1690. DoIO(diskreq);
  1691. return(TRUE);
  1692. }
  1693.  
  1694. unsigned long *OpenLibVectorPtr;
  1695. unsigned long *EntryForOldOpenLib;
  1696. unsigned long *OldOldOpenLibVector;
  1697.  
  1698.  
  1699. CheckMemoryForIRQVirus()
  1700. {
  1701. long *Array;
  1702. int Num;
  1703.  
  1704. Array = (long *)4;
  1705. Array = (long *)Array[0];
  1706. Num = (int)Array;
  1707. Num = Num - 0x196;
  1708.  
  1709. OpenLibVectorPtr = (unsigned long *)Num;
  1710.  
  1711. EntryForOldOpenLib = (unsigned long *)OpenLibVectorPtr[0];
  1712. OldOldOpenLibVector = (unsigned long *)(((char *)EntryForOldOpenLib) + 0x12);
  1713.  
  1714. if (EntryForOldOpenLib[0] == 0x2f3a0010)
  1715.         {
  1716.         OpenLibVectorPtr[0] = OldOldOpenLibVector[0];
  1717.         ExecBase->KickTagPtr = 0;
  1718.         MyRequest(VN_IRQ, 2);
  1719.         };
  1720. }
  1721.  
  1722.  
  1723. /********************************/
  1724.  
  1725. CheckDriveForIRQ(drivename)
  1726. char *drivename;
  1727. {
  1728. int err;
  1729. char buffer[80];
  1730. char dirbuffer[80];
  1731. char filebuffer[100];
  1732. char tempbuffer[100];
  1733. char FoundInDir;
  1734. char FoundInFname;
  1735. char chr;
  1736. int index;
  1737. char pass;
  1738.  
  1739. FoundInDir = FALSE;
  1740. FoundInFname = FALSE;
  1741. filebuffer[0] = 0;
  1742.  
  1743. pass = 0;
  1744.  
  1745. sprintf(dirbuffer, "%sC/DIR", drivename);
  1746. err = CheckFileForIRQ(dirbuffer,0);
  1747. if (err == 1)
  1748.         {
  1749.         IRQFound++;
  1750.         FoundInDir = TRUE;
  1751.         }
  1752.         else dirbuffer[0] = 0;
  1753.  
  1754.  
  1755. index = 0;
  1756.  
  1757. sprintf(tempbuffer, "%ss/Startup-Sequence", drivename);
  1758. fp = Open(tempbuffer, MODE_OLDFILE);
  1759. if (fp == 0)
  1760.         filebuffer[0] = 0;
  1761.         else
  1762.         {
  1763.         while (TRUE)
  1764.                 {
  1765.                 err = Read(fp, &chr, 1);
  1766.                 if (err == 0) break;
  1767.                 if ((chr == 34) || (chr == 0x0a) || (chr == ';') || (chr == ' ')) continue;
  1768.                 break;
  1769.                 };
  1770.  
  1771.         if (err != 0)
  1772.                 {
  1773.                 while (TRUE)
  1774.                         {
  1775.                         filebuffer[index++] = chr;
  1776.                         filebuffer[index] = 0;
  1777.                         err = Read(fp, &chr, 1);
  1778.                         if (err == 0) break;
  1779.                         if (chr == 34) break;
  1780.                         if (chr == 0x0a) break;
  1781.                         if (chr == ';') break;
  1782.                         if (chr == 32) break;
  1783.                         };
  1784.                 };
  1785.  
  1786.         Close(fp);
  1787.  
  1788.         sprintf(buffer, "%s%s", drivename, filebuffer);
  1789.  
  1790.         err = CheckFileForIRQ(buffer, 0);
  1791.         if (err == -1)
  1792.                 {
  1793.                 sprintf(buffer, "C:%s", filebuffer);
  1794.                 err = CheckFileForIRQ(buffer, 0);
  1795.                 };
  1796.  
  1797.         strcpy(filebuffer, buffer);
  1798.  
  1799.         if (err == 1)
  1800.                 {
  1801.                 FoundInFname = TRUE;
  1802.                 IRQFound++;
  1803.                 }
  1804.                 else filebuffer[0] = 0;
  1805.         };
  1806.  
  1807. if (FoundInDir == FALSE && FoundInFname == FALSE) return(0);
  1808.  
  1809. WBenchToFront();
  1810. fp = Open("CON:70/20/500/100/VirusX", MODE_NEWFILE);
  1811. if (fp == 0) return(0);
  1812.  
  1813. WriteFP(fp, "NOTICE:  The IRQ Virus was found on volume ");
  1814. WriteFP(fp, drivename);
  1815. WriteFP(fp, "\n");
  1816.  
  1817. while (TRUE)
  1818.         {
  1819.         if (pass == 0)
  1820.                 {
  1821.                 strcpy(tempbuffer, dirbuffer);
  1822.                 }
  1823.         else if (pass == 1)
  1824.                 {
  1825.                 strcpy(tempbuffer, filebuffer);
  1826.                 }
  1827.         else if (pass == 2) break;
  1828.  
  1829.         pass++;
  1830.  
  1831.         if (tempbuffer[0] == 0) continue;
  1832.  
  1833.         sprintf(buffer, "\nIn the command: %s\n", tempbuffer);
  1834.         WriteFP(fp, buffer);
  1835.         WriteFP(fp, "Okay to remove it? [Y]: ");
  1836.         Read(fp, buffer, 3);
  1837.         if (toupper(buffer[0]) == 'Y')
  1838.                 {
  1839.                 err = CheckFileForIRQ(tempbuffer, 1);
  1840.                 if (err == 1)
  1841.                         {
  1842.                         WriteFP(fp, "Virus removed.\n");
  1843.                         } else
  1844.                         {
  1845.                         WriteFP(fp, "Error removing virus.  Check file.\n");
  1846.                         }
  1847.                 };
  1848.         };
  1849.  
  1850. WriteFP(fp, "\nHit RETURN to continue...");
  1851. Read(fp, buffer, 3);
  1852. Close(fp);
  1853. }
  1854.  
  1855. WriteFP(fp, string)
  1856. int fp;
  1857. char *string;
  1858. {
  1859. Write(fp, string, strlen(string));
  1860. }
  1861.  
  1862. /********************************/
  1863.  
  1864. #define VTAG     0x00000109L
  1865. #define BEGIN    OFFSET_BEGINNING
  1866. #define END              OFFSET_END
  1867. #define OLD              MODE_OLDFILE
  1868. #define NEW              MODE_NEWFILE
  1869. #define SLONG    ((long)sizeof(long))
  1870. #define OK        1                     /* no error */
  1871.  
  1872. #define NOFILE   -1                     /* can't find file */
  1873. #define SEEKERR  -2                     /* seek error on file */
  1874. #define ALLOCERR -3                     /* can't allocate memory */
  1875. #define READERR  -4                     /* error reading file */
  1876. #define VIRUSNF  -5                     /* virus not found in file */
  1877. #define WRITERR  -6                     /* error writing to file */
  1878. #define OPENERR  -7                     /* error opening file for write */
  1879. #define NOTEXE   -8                     /* not an executable file */
  1880.  
  1881. #define GOTHIM   OK                     /* removed virus from file */
  1882.  
  1883. #define VTAG     0x00000109L            /* virus hunk length */
  1884. #define VSIG1    0x0000FFFEL            /* part of virus signature */
  1885. #define VSIG2    0x61000000L            /* part of virus signature */
  1886.  
  1887.  
  1888. static long inp, *buff, size;
  1889.  
  1890. cleanup(val)
  1891. int val;
  1892. {
  1893.         if(inp)         Close(inp);
  1894.         if(buff)        FreeMem(buff,size);
  1895.         return val;
  1896. }
  1897.  
  1898. CheckFileForIRQ(fname, flag)
  1899. char *fname;
  1900. int flag;
  1901. {
  1902.  
  1903.         int   i = 0;
  1904.         long  nhunk;
  1905.         long tbuff[488/4];
  1906.  
  1907.         inp = 0L;  buff = 0L;
  1908.  
  1909.         if((inp = Open(fname,OLD)) == 0)        /* open the desired file */
  1910.                 return NOFILE;
  1911.  
  1912.         Read(inp,(char *)&tbuff[0],487);                                /* get the first long word */
  1913.         if(tbuff[0] != 0x000003F3)                              /* check for executable file */
  1914.                 return cleanup(NOTEXE);
  1915.  
  1916.         if(tbuff[5] != VTAG)
  1917.                 return cleanup(VIRUSNF);
  1918.  
  1919.         Seek(inp,0L,END);                               /* seek to end of file */
  1920.         size = Seek(inp,0L,BEGIN);              /* rewind the file to get size */
  1921.         if(size <= 0L)
  1922.                 return cleanup(SEEKERR);
  1923.  
  1924.         if((buff = AllocMem(size,0L)) == 0)     /* mem buffer for file */
  1925.                 return cleanup(ALLOCERR);
  1926.  
  1927.         if(Read(inp,(char *)&buff[0],size) != size)     /* read entire file into buffer */
  1928.                 return cleanup(READERR);
  1929.  
  1930.         nhunk = buff[ 2 ];              /* number of hunks in file */
  1931.  
  1932. /*
  1933.         the IRQ virus inserts his code as the first hunk in the file
  1934.         we can find the first hunk in the 6th longword of the file
  1935. */
  1936.         /* find the start of the virus hunk */
  1937.         while(buff[ i++ ] != 0x000003E9)
  1938.                 ;
  1939. /*
  1940.         The virus checks the first hunk for it's signature to prevent
  1941.          reinfecting an already infected program.  It actually checks for
  1942.         0xFFFE6100 which is the lower half of a move.m instruction and
  1943.         the upper half of a bsr instruction.  Here we do the same.
  1944.     i points to the virus code hunk length.
  1945. */
  1946.         if( ((buff[ i+1 ] & 0x0000FFFF) != VSIG1)
  1947.      || ((buff[ i+2 ] & 0xFFFF0000) != VSIG2) )
  1948.                 return cleanup(VIRUSNF);
  1949.  
  1950.         if (flag == 0)
  1951.                 return cleanup(1);
  1952.  
  1953. /*
  1954.         close the file and reopen it with write access
  1955.         mode NEW will effectivly delete the old file contents so if a
  1956.         file error occurs before we finish, the file will be corrupt
  1957. */
  1958.         Close(inp);
  1959.         if((inp = Open(fname,NEW)) == 0)
  1960.                 return cleanup(OPENERR);
  1961.  
  1962.         buff[2] -= 1;   buff[4] -= 1;   /* readjust program header info */
  1963.  
  1964. /* write new header */
  1965.         if(Write(inp,(char *)&buff[0],5L*SLONG) != 5L*SLONG)
  1966.                 return cleanup(WRITERR);
  1967.  
  1968.         if(Write(inp,(char *)&buff[6],nhunk*SLONG) != nhunk*SLONG)
  1969.                 return cleanup(WRITERR);
  1970.  
  1971. /*
  1972.         subtract length of virus hunk and overhead from file size
  1973.         i was calculated earlier
  1974. */
  1975.         i = i + 8L + VTAG;
  1976.         size = (size/SLONG - i)*SLONG;
  1977.  
  1978. /* and write old code out to file, ignoring virus hunk */
  1979.         if(Write(inp,(char *)&buff[i],size) != size)
  1980.                 return cleanup(WRITERR);
  1981.  
  1982. /* we're done, the file is clean and intact */
  1983.         return cleanup(GOTHIM);
  1984. }
  1985.